package com.user.gamecenter.network.retrofit;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.google.gson.JsonParseException;
import com.user.gamecenter.BuildConfig;
import com.user.gamecenter.network.RetrofitManager;
import com.user.gamecenter.network.body.ProgressResponseBody;
import com.user.gamecenter.network.help.BaseUrl;
import com.user.gamecenter.utils.NetworkUtil;

import org.json.JSONException;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import io.reactivex.schedulers.Schedulers;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Converter;
import retrofit2.HttpException;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;


/**
 * author : Administrator
 * e-mail : 254419013@qq.com
 * time   : 2017/05/18
 * desc   :
 */
public class StaticRetrofitManager extends RetrofitManager {

    private static final String TAG = "StaticRetrofitManager";

    private static Context context = null;

    //baseUrl
    private static Map<Integer, BaseUrl> baseUrlMap = new HashMap<>();

    //okHttpClient
    private static Map<BaseUrl, OkHttpClient> okHttpClientMap = new HashMap<>();

    //retrofit
    private static Map<OkHttpClient, Retrofit> retrofitMap = new HashMap<>();

    public StaticRetrofitManager(Context context) {
        this.context = context;
    }

    public StaticRetrofitManager() {
    }

    /**
     * @方法名: 创建通常的OKHttp
     * @参数：
     * @返回值：
     * @描述:
     * @作者： cms
     * @创建日期 2016/12/15 20:09
     */
    public static OkHttpClient createOkHttpClient(BaseUrl baseUrl) {

        if (okHttpClientMap.containsKey(baseUrl)) {
            if (BuildConfig.DEBUG) Log.d(TAG, "有包含OkHttpClient -----------------");
            return okHttpClientMap.get(baseUrl);
        }

        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        Interceptor authorizationInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {

                Request request = chain.request();
                long t1 = System.nanoTime();
                Log.d(TAG, String.format("Sending request %s on %s%n%s", request.url(),
                        chain.connection(), request.headers()));

                Response response = chain.proceed(request);
                long t2 = System.nanoTime();
                Log.d(TAG, String.format("Received response for %s in %.1fms%n%s",
                        response.request().url(), (t2 - t1) / 1e6d, response.headers()));

                return response;
            }
        };
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
               .addInterceptor(interceptor)//设置应用拦截器
                .retryOnConnectionFailure(false) //错误重联
                .connectTimeout(10, TimeUnit.SECONDS)//链接超时
                .readTimeout(10, TimeUnit.SECONDS)//读取超时
               .addNetworkInterceptor(authorizationInterceptor)//网络拦截器
                .build();

        if (BuildConfig.DEBUG) Log.d(TAG, "新建OkHttpClient -----------------");
        okHttpClientMap.put(baseUrl, okHttpClient);
        return okHttpClient;
    }

    /**
     * @方法名: 创建有响应进度的OKHttp
     * @参数：
     * @返回值：
     * @描述:
     * @作者： cms
     * @创建日期 2016/12/13 10:20
     */
    public static OkHttpClient createResponseProgressOkHttpClient(final ProgressResponseBody.ProgressListener progressListener, BaseUrl baseUrl) {

        if (okHttpClientMap.containsKey(baseUrl)) {
            if (BuildConfig.DEBUG) Log.d(TAG, "有包含OkHttpClient -----------------");
            return okHttpClientMap.get(baseUrl);
        }

        Interceptor authorizationInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {

                Response originalResponse = chain.proceed(chain.request());
                return originalResponse.newBuilder().body(new ProgressResponseBody(originalResponse.body(), progressListener)).build();

            }
        };
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(authorizationInterceptor)//设置应用拦截器
                .retryOnConnectionFailure(false) //错误重联
                .connectTimeout(120, TimeUnit.MINUTES)//链接超时
                .readTimeout(120, TimeUnit.MINUTES)//读取超时
                .build();

        if (BuildConfig.DEBUG) Log.d(TAG, "新建OkHttpClient -----------------");
        okHttpClientMap.put(baseUrl, okHttpClient);
        return okHttpClient;
    }

    /**
     * @方法名: 创建有请求进度的OKHttp
     * @参数：
     * @返回值：
     * @描述:
     * @作者： cms
     * @创建日期 2016/12/13 10:20
     */
    public static OkHttpClient createRequestProgressOkHttpClient(BaseUrl baseUrl) {

        if (okHttpClientMap.containsKey(baseUrl)) {
            if (BuildConfig.DEBUG) Log.d(TAG, "有包含OkHttpClient -----------------");
            return okHttpClientMap.get(baseUrl);
        }

        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .retryOnConnectionFailure(false) //错误重联
                .connectTimeout(120, TimeUnit.MINUTES)//链接超时
                .readTimeout(120, TimeUnit.MINUTES)//读取超时
                .build();
        if (BuildConfig.DEBUG) Log.d(TAG, "新建OkHttpClient -----------------");
        okHttpClientMap.put(baseUrl, okHttpClient);
        return okHttpClient;
    }

    /**
     * @方法名: 创建基础URL
     * @参数：
     * @返回值：
     * @描述:
     * @作者： cms
     * @创建日期 2016/12/15 20:11
     */
    public static BaseUrl createBaseUrl(Object url) {

        String baseUrlString = null;
        HttpUrl baseUrlHttpUrl = null;

        if (url instanceof String) {
            baseUrlString = (String) url;
            baseUrlHttpUrl = null;
        } else if (url instanceof HttpUrl) {
            baseUrlString = null;
            baseUrlHttpUrl = (HttpUrl) url;
        }

        //算出哈希值
        int result = baseUrlString != null ? baseUrlString.hashCode() : 0;
        result = 31 * result + (baseUrlHttpUrl != null ? baseUrlHttpUrl.hashCode() : 0);

        if (baseUrlMap.containsKey(result)) {
            if (BuildConfig.DEBUG) Log.d(TAG, "有包含BaseUrl -----------------");
            return baseUrlMap.get(result);
        } else {
            BaseUrl baseUrl = new BaseUrl(baseUrlString, baseUrlHttpUrl);
            if (BuildConfig.DEBUG) Log.d(TAG, "新建BaseUrl -----------------");
            baseUrlMap.put(baseUrl.hashCode(), baseUrl);
            return baseUrl;
        }
    }

    /**
     * @方法名: 创建Retrofit
     * @参数：
     * @返回值：
     * @描述:
     * @作者： cms
     * @创建日期 2016/12/15 20:18
     */
    public static Retrofit createRetrofit(Converter.Factory factory, BaseUrl baseUrl) {

        if (okHttpClientMap.containsKey(baseUrl)) {
            if (retrofitMap.containsKey(okHttpClientMap.get(baseUrl))) {
                if (BuildConfig.DEBUG) Log.d(TAG, "有包含Retrofit -----------------");
                return retrofitMap.get(okHttpClientMap.get(baseUrl));
            }
        }
        Retrofit retrofit;
        if (baseUrl.getBaseUrlString() != null && baseUrl.getBaseUrlHttpUrl() == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl.getBaseUrlString())
                    .client(okHttpClientMap.get(baseUrl))
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))//适配器
                    .addConverterFactory(factory)//转换层
                    .build();
        } else if ((baseUrl.getBaseUrlString() == null && baseUrl.getBaseUrlHttpUrl() != null)) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl.getBaseUrlHttpUrl())
                    .client(okHttpClientMap.get(baseUrl))
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))//适配器
                    .addConverterFactory(factory)//转换层
                    .build();
        } else {
            retrofit = null;
        }
        if (BuildConfig.DEBUG) Log.d(TAG, "新建Retrofit -----------------");
        retrofitMap.put(okHttpClientMap.get(baseUrl), retrofit);
        return retrofit;
    }


    public static void errorInfo(Throwable e) {
        Throwable throwable = e;
        /**
         * 获取根源 异常
         */
        while (throwable.getCause() != null) {
            e = throwable;
            throwable = throwable.getCause();
        }
        if (e instanceof HttpException) {//对网络异常
            HttpException httpException = (HttpException) e;
            if (TextUtils.isEmpty(httpException.getMessage())) {
                Log.d(TAG, "1------------ error_net_fail");
            } else {
                String errorMsg = httpException.getMessage();
                if (TextUtils.isEmpty(errorMsg)) {
                    Log.d(TAG, "1------------ error_net_fail");
                } else {
                    Log.d(TAG, "1------------ " + errorMsg);
                }

            }
        } else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException) {//解析异常
            Log.d(TAG, "1------------ error_net_parse");
        } else if (e instanceof UnknownHostException) {//未知主机
            Log.d(TAG, "1------------ 未知主机");
        } else if (e instanceof SocketTimeoutException) {//网络链接超时
            Log.d(TAG, "1------------ 网络链接超时");
        } else {//未知错误
            if (context != null) {
                if (NetworkUtil.isNetWorkAvailable(context)) {
                    Log.d(TAG, "1------------ error_inner_error");
                    e.printStackTrace();//对于未知错误进行打印,大部分为程序逻辑错误
                } else {
                    Log.d(TAG, "1------------ 无网络");
                }
            } else {
                if (NetworkUtil.isNetWorkAvailable()) {
                    Log.d(TAG, "1------------ error_inner_error");
                    e.printStackTrace();//对于未知错误进行打印,大部分为程序逻辑错误
                } else {
                    Log.d(TAG, "1------------ 无网络");
                }
            }
        }
    }
}
